#函数进阶
#作用域、匿名函数、内置函数、拆包

#一、作用域
'''
定义：作用的范围（名称空间）
按照生效的范围，分为全局作用域和局部作用域
命名空间：本质是从名称到对象的映射，一一对应的关系，通过字典来实现。
比如：a = 10 定义这个变量时，python会申请内存空间存放10，然后将名字a与10
绑定关系存放在名称空间中。
如何清除绑定关系：del(a)
'''
#名称空间：
#内置名称空间：随着python解析器启动而产生，停止而收回。(第一个被加载)
#全局名称空间：随所在执行文件而产生，执行结束而收回。（第二个被加载）
#局部名称空间：随着函数被调用而产生，随结束调用而收回。（函数参数、函数内名字）
'''
全局作用域：包括内置命名空间和全局命名空间
局部作用域：在函数内可以调用
'''
#python查找变量的顺序：局部的命名空间-->全局命名空间-->内置命名空间



#变量的作用域
'''
局部变量:函数内部定义的变量，从定义位置开始到函数定义结束位置有效。
注意：函数间不能共享内部定义的变量格式；函数内可以使用全局变量。

全局变量：函数外部定义的变量，在整个文件中有效。（作用范围是当前的文件）
'''
a = 100       #此处的a为全局变量。
def funa():
    a = 200   #此处的a为局部变量，与全局变量同名，只能在函数内部被调用。
    print(a)
def funb():
    print(a)  #此处的a调用的是外部的全局变量。
funa()
funb()
print('\n')

#关键字global  nonlocal
'''
global:将变量声明为全局变量，语法格式：global变量名

nonlocal:将变量声明为外层变量（外层函数的局部变量，而且不能是全局变量）
'''
#golbal

#不可变对象变量
a = 1
def funb():
    global a  #声明a为全局变量
    print(a)
    a = 2     #修改全局变量的值
funb()        #1
print(a)      #2
print('\n')

#可变对象变量（可以不声明）
list1 = [1,2,3,4]
def fun():
    list1[0]=5   #list1指向的地址没有变化，而值发生了变化。
    print(list1)
fun()
print('\n')


#nonlocal
'''不能修改全局变量
在局部作用域中，对父级作用的变量进行引用和修改，并且引用的哪层，就从那层开始及
以下，此变量全部发生改变。
'''
a = 10
def funa1():
    a = 1
    def funb1():
        nonlocal a  #声明a为外层函数的变量
        print('funb1函数中的a的值',a)
        a = 20
    funb1()
    print('funa1函数中的a的值',a)
funa1()
print(a)

       





